<template>
    <div>
        <template v-if="mode === 'default'">
            <input ref="pickerInput" />
        </template>

        <template v-else-if="mode === 'input'">
            <div class="color-input" ref="pickerInput">
                <span class="color-block" :style="{backgroundColor: data.colorValue}"></span>
            </div>
        </template>

        <template v-else-if="mode === 'slot'">
            <div class="color-slot" ref="pickerInput">
                <slot></slot>
            </div>
        </template>
    </div>
</template>

<script setup>
import { ref, reactive, onMounted, onBeforeUnmount, watch } from 'vue';
import Pickr from '@simonwep/pickr';
import '@simonwep/pickr/dist/themes/classic.min.css';   // 'classic' theme
import '@simonwep/pickr/dist/themes/monolith.min.css';  // 'monolith' theme
import '@simonwep/pickr/dist/themes/nano.min.css';      // 'nano' theme

const emit = defineEmits(['update:modelValue', 'change'])

const pickerInput = ref(null);

const data = reactive({
    pickr: null,
    colorValue: '',
})

const props = defineProps({
    // 显示模式
    mode: { type: String, default: 'default' },   // default、input、slot
    // 面板主题
    theme: { type: String, default: 'nano' },  // classic、monolith、nano
    // 颜色值
    modelValue: { type: String, default: '' },
    // 是否禁用
    disabled: { type: Boolean, default: false },
})

watch(() => props.modelValue, (newValue, oldValue) => {
    data.colorValue = newValue;
});

// 挂载DOM后触发
onMounted(() => {
    if (props.modelValue != "" && props.modelValue != null && props.modelValue != undefined) {
        data.colorValue = props.modelValue;
    } else {
        data.colorValue = "#5A5A5A";
    }

    let options = {
        cancel: false,
        clear: false,
        save: false,
    }

    if (props.mode == 'default') {
        options = {
            cancel: true,
            clear: true,
            save: true,
        }
    }

    data.pickr = new Pickr({
        el: pickerInput.value,
        theme: props.theme, //'classic' or 'monolith', or 'nano'
        // 默认颜色。如果你正在使用一种命名的颜色，如红色、白色。。。设置
        // defaultRepresentation的值，因为没有用于命名颜色的按钮。
        default: data.colorValue,

        // 不要将'el'元素替换为picker按钮，而是使用'el'作为按钮
        // 如果为true，appendToBody也将自动为true
        useAsButton: props.mode == 'default' ? false : true,

        // 开始状态。如果为true，则“disabled”将添加到按钮的类列表中。
        disabled: props.disabled,

        // 添加到pcr应用程序的自定义类。可用于应用自定义样式。
        appClass: 'dc-pcr',

        // 输入/输出文本框的默认颜色表示。
        // 有效选项为“HEX”、“RGBA”、“HSVA”、“HSVA”和“CMYK”。
        defaultRepresentation: 'HEX',

        // 定义更改/保存行为：
        // -要在按下Save（保存）之前保持当前颜色不变，请设置为“true”，
        // -将颜色应用于按钮，并与每次更改同步预览（保存）
        //（从选择器或调色板），设置为“false”。
        comparison: false,

        // 可选色样。为null时，样例将被禁用。
        // 类型是所有可以由picker生成的类型，例如hex（a）、hsv（a），hsl（a）和rgb（a）以及cmyk，还有CSS颜色名称，如“品红色”。
        // 示例：样例：[“#F44336”、“#E91E63”、“#9C27B0”、“#1673AB7”]，
        swatches: [
            'rgba(244, 67, 54, 1)',
            'rgba(233, 30, 99, 0.95)',
            'rgba(156, 39, 176, 0.9)',
            'rgba(103, 58, 183, 0.85)',
            'rgba(63, 81, 181, 0.8)',
            'rgba(33, 150, 243, 0.75)',
            'rgba(3, 169, 244, 0.7)',
            'rgba(0, 188, 212, 0.7)',
            'rgba(0, 150, 136, 0.75)',
            'rgba(76, 175, 80, 0.8)',
            'rgba(139, 195, 74, 0.85)',
            'rgba(205, 220, 57, 0.9)',
            'rgba(255, 235, 59, 0.95)',
            'rgba(255, 193, 7, 1)',
            'rgba(255, 255, 255, 0)'
        ],
        //显示或隐藏特定组件。
        //默认情况下，只有选项板（和保存按钮）可见。
        components: {

            //定义调色板本身是否可见。
            //如果预览、不透明度或色调为true，将用true覆盖
            palette: true,

            preview: true, // 显示以前状态和新颜色之间的比较
            opacity: true, // 显示不透明度滑块
            hue: true,     // 显示色调滑块

            // 在底部交互栏上显示或隐藏组件。
            interaction: {

                // 按钮，如果您禁用了一个按钮，但默认使用格式：或setColor（）-也设置表示类型！
                hex: true,  // 显示“输入/输出格式为十六进制”按钮（rgba值的十六进制表示）
                rgba: true, // 显示“输入/输出格式为rgba”按钮（红色、绿色、蓝色和alpha）
                hsla: true, // 显示“输入/输出格式为hsla”按钮（色调饱和度亮度和alpha）
                hsva: false, // 显示“输入/输出格式为hsva”按钮（色调饱和度值和alpha）
                cmyk: false, // 显示“输入/输出格式为cmyk”按钮（青色Manganta黄色键）

                input: true, // 显示显示所选颜色值的输入/输出文本框。
                // 输入的格式由defaultRepresentation确定，
                // 用户可以通过十六进制、rgba、hsla等设置的按钮进行更改（如上）。
                cancel: options.cancel, // 显示取消按钮，将颜色重置为以前的状态
                clear: options.clear,  // 显示清除按钮；与取消相同，但保持窗口打开
                save: options.save,   // 显示保存按钮，
            },
        },

        // picker应用程序应添加为子应用程序的位置
        // container: 'body',

        // 目前不支持嵌套滚动，因此添加此项非常复杂
        // 如果用户滚动picker后面的区域，则更容易将其设置为true，从而隐藏picker
        // closeOnScroll: false,

        // picker（小部件）和相应引用（按钮）之间的间隙大小，单位为px
        // padding: 8,

        // 如果true picker将不浮动，而是将附加在in-el解析的元素之后。
        // 无论如何都可以通过.hide（）隐藏它。
        // inline: false,

        // 如果为true，picker将在页面滚动或窗口调整时自动重新定位。
        // 可以设置为false以使自定义定位更容易。
        // autoReposition: true,

        // 定义可以移动色调和不透明度旋钮的方向。
        // 'v'=>不透明度和色调滑块都只能垂直移动。
        // “hv”=>不透明度滑块可以水平移动，色调滑块可以垂直移动。
        // 可用于应用自定义布局
        // sliders: 'v',

        // 如果为true，则用户将无法调整任何不透明度。
        // 不透明度将锁定在1，并且不透明度滑块将被移除。
        // HSVaColor对象也不包含alpha，所以toString（）方法只是
        // 打印HSV、HSL、RGB、HEX等。
        // lockOpacity: false,

        // 输出字符串的精度（仅当components.interaction.input为true时有效）
        // outputPrecision: 0,

        // 保持颜色选择器始终可见的选项。
        // 您仍然可以通过“pick.hide（）”和“pick.show（）”隐藏/显示它。
        // 保存按钮保持其功能，因此单击时仍会触发onSave事件。
        // showAlways: false,

        // 用按键关闭拾取器。
        // 默认为“Escape”。可以是事件键或代码。
        // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key)
        // closeWithKey: 'Escape',

        //定义颜色选择器的位置。
        //top, left, bottom right 与以下可选修饰符之一的任意组合：开始start, 中间middle, 结束end
        //示例：顶部起点/右侧终点
        //如果发生剪切，颜色选择器将自动选择其位置。
        //拾取器使用https://github.com/Simonwep/nanopop作为定位引擎。
        // position: 'bottom-middle',

        //允许使用滚轮更改输入字段中的数字。
        //要使用它，请将光标设置在数字所在的位置并滚动，使用ctrl以五步为一步
        // adjustableNumbers: true,

        // Translations, these are the default values.
        // i18n: {
        //     // Strings visible in the UI
        //     'ui:dialog': 'color picker dialog',
        //     'btn:toggle': 'toggle color picker dialog',
        //     'btn:swatch': 'color swatch',
        //     'btn:last-color': 'use previous color',
        //     'btn:save': 'Save',
        //     'btn:cancel': 'Cancel',
        //     'btn:clear': 'Clear',

        //     // Strings used for aria-labels
        //     'aria:btn:save': 'save and close',
        //     'aria:btn:cancel': 'cancel and close',
        //     'aria:btn:clear': 'clear and close',
        //     'aria:input': 'color input field',
        //     'aria:palette': 'color selection area',
        //     'aria:hue': 'hue selection slider',
        //     'aria:opacity': 'selection slider'
        // }
    });

    data.pickr.on('init', instance => {
        // 初始化的回调
    }).on('hide', instance => {
        // 面板隐藏的回调
    }).on('show', (color, instance) => {
        // 面板显示的回调
    }).on('save', (color, instance) => {
        // 面板点击保存按钮的回调
    }).on('clear', instance => {
        // 面板点击清除按钮的回调
    }).on('change', (color, source, instance) => {
        // 面板颜色改变的回调
        colorChange(color, source, instance);
    }).on('changestop', (source, instance) => {
        // 面板颜色改变停止的回调
    }).on('cancel', instance => {
        // 面板点击取消按钮的回调
    }).on('swatchselect', (color, instance) => {
        // console.log('Event: "swatchselect"', color, instance);
    });

    // console.log("picker:", data.pickr)

})


/**
 * 颜色改变时触发
 * @param {*} color 
 * @param {*} source 
 * @param {*} instance 
 */
const colorChange = (color, source, instance) => {
    // console.log('change:color:', color);
    // console.log('change:source:', source);
    // console.log('change:instance:', instance);
    let representation = instance._representation;  // 颜色数据类型
    if (representation == 'HEXA') {
        data.colorValue = color.toHEXA().toString();
    } else if (representation == 'RGBA') {
        let rgba = color.toRGBA();
        data.colorValue = `rgba(${Math.round(rgba[0])},${Math.round(rgba[1])},${Math.round(rgba[2])},${rgba[3]})`;
    } else if (representation == 'HSLA') {
        let hsla = color.toHSLA();
        data.colorValue = `hsla(${Math.round(hsla[0])},${Math.round(hsla[1])}%,${Math.round(hsla[2])}%,${hsla[3]})`;
    }
    emit('update:modelValue', data.colorValue);
    emit('change', data.colorValue);
}

// 组件卸载前触发
onBeforeUnmount(() => {
    if (data.pickr) {
        data.pickr.destroy();
    }
});
</script>


<style lang="less" scoped>
.color-input {
    width: 100%;
    height: 32px;
    padding: 0 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    cursor: pointer;
    border: 1px solid #dcdfe6;

    .color-block {
        width: 100%;
        display: block;
        height: 20px;
        border-radius: 4px;
    }
}

.color-slot {
    width: 100%;
    cursor: pointer;
}
</style>

<style>
.dc-pcr {
    width: 278px !important;
}
</style>